package com.greateamd.timetableasy.client.mvc.view.crud.user;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.greateamd.timetableasy.client.domain.AuthType;
import com.greateamd.timetableasy.client.mvc.model.Model;
import com.greateamd.timetableasy.client.services.user.UserService;
import com.greateamd.timetableasy.client.services.user.UserServiceAsync;
import com.greateamd.timetableasy.client.services.util.ServerCall;
import com.greateamd.timetableasy.client.widgets.AuthListBox;
import com.greateamd.timetableasy.client.widgets.EntityContainer;
import com.greateamd.timetableasy.client.widgets.MessagePopupPanel;
import com.greateamd.timetableasy.client.widgets.campus.PromotionListBox;
import com.greateamd.timetableasy.domain.Auth;
import com.greateamd.timetableasy.domain.User;

public class EditUserPage <M extends Model> extends IEditUserPage<M>{

	private final UserServiceAsync userService = GWT.create(UserService.class);

	@UiTemplate("EditUserPage.ui.xml")
	interface EditUserPageUIBinder extends UiBinder<Widget, EditUserPage> {}
	private static EditUserPageUIBinder uiBinder = GWT.create(EditUserPageUIBinder.class);

	//Search
	@UiField TextBox searchUsername;
	@UiField Button searchBt;
	//Attributes
	@UiField TextBox username;
	@UiField TextBox firstname;
	@UiField TextBox lastname;
	@UiField PasswordTextBox password;
	@UiField TextBox age;
	@UiField TextBox address;
	@UiField CheckBox enabled;
	//Auth
	@UiField AuthListBox listAllAuth;
	@UiField EntityContainer<Auth> listUserAuth;
	@UiField Button addAuthBt;
	@UiField Button rmAuthBt;
	//Promotion
	@UiField PromotionListBox promotionLb;
	
	private User foundUser;
	
	/**
	 * Constructor
	 */
	public EditUserPage() {
	    initWidget(uiBinder.createAndBindUi(this));
	}
	
	@Override
	public Widget getWidgetPage() {
		return this;
	}

	@Override
	public void setUser(User user) {
	}


	//---------------------------------------------------------------------
	//-------------------------- UI action
	public void fillUserPanel(User user) {
		username.setText(user.getUsername());
		lastname.setText(user.getLastname());
		firstname.setText(user.getUsername());
		password.setText (user.getPassword());
		age.setText(Integer.toString(user.getAge()));
		address.setText(user.getAddress());
		enabled.setValue(user.isEnabled());
		promotionLb.setSelectedPromotion(user.getPromotion());
		
		listUserAuth.clear();
		for(Auth right : user.getAuths()){
			listUserAuth.addEntity(right);
		}
	}
	
	//---------------------------------------------------------------------
	//-------------------------- Handler
	
	@UiHandler("addAuthBt")
	void onAddAuthBtClick(ClickEvent e){
		if(listAllAuth.getSelectedIndex() != -1){
			if(listUserAuth.addEntity(new Auth(foundUser,listAllAuth.getSelectedAuthType()))){
				addUserAuth(listAllAuth.getSelectedAuthType());
			}
		}
	}
	@UiHandler("rmAuthBt")
	void onRmAuthBtClick(ClickEvent e){
		if(listUserAuth.getSelectedIndex() != -1){
//			foundUser.getAuths().remove(new Auth(foundUser,listUserAuth.getItemText(listUserAuth.getSelectedIndex())));
			removeUserAuth(AuthType.valueOf(listUserAuth.getItemText(listUserAuth.getSelectedIndex())));
			listUserAuth.removeItem(listUserAuth.getSelectedIndex());
		}
	}
	@UiHandler("submitBt")
	void onSubmitBtClick(ClickEvent e){
		editUser();
	}
	@UiHandler("searchBt")
	void onSearchBtClick(ClickEvent e){
		searchUser();
	}

	//---------------------------------------------------------------------
	//-------------------------- Server call
	
	private void editUser() {
		if(!checkFormValidity()){
			Window.alert("Invalid form");
			return;
		}
		new ServerCall<Boolean>() {

			@Override
			protected void callService(AsyncCallback<Boolean> asyncCallback) {
				foundUser.setAge(Integer.parseInt(age.getValue()));
				foundUser.setFirstname(firstname.getValue());
				foundUser.setLastname(lastname.getValue());
				foundUser.setAddress(address.getValue());
				foundUser.setPassword(password.getValue());
				foundUser.setEnabled(enabled.getValue());
				foundUser.setPromotion(promotionLb.getSelectedPromotion());
				userService.update(foundUser,asyncCallback);
			}

			@Override
			public void onSuccess(Boolean success) {
				if(success)
					new MessagePopupPanel("Success","User has well been edited").show();
				else
					new MessagePopupPanel("Error","Operation failed").show();
			}
		}.call();
	}

	private void searchUser() {
		new ServerCall<User>() {

			@Override
			protected void callService(AsyncCallback<User> asyncCallback) {
				userService.find(searchUsername.getText(),asyncCallback);
			}

			@Override
			public void onSuccess(User result) {
				if(result==null)
					Window.alert("User not found");
				else{
					foundUser = result;
					fillUserPanel(result);
				}
			}
		}.call();
	}

	private void addUserAuth(final AuthType auth) {
		new ServerCall<Boolean>() {

			@Override
			protected void callService(AsyncCallback<Boolean> asyncCallback) {
				userService.addUserAuth(foundUser, auth, asyncCallback);
			}

			@Override
			public void onSuccess(Boolean success) {
				Window.alert("Success " +success);
			}
		}.call();
	}
	
	private void removeUserAuth(final AuthType auth) {
		new ServerCall<Boolean>() {

			@Override
			protected void callService(AsyncCallback<Boolean> asyncCallback) {
				userService.removeUserAuth(foundUser, auth, asyncCallback);
			}

			@Override
			public void onSuccess(Boolean success) {
				Window.alert("Success " +success);
			}
		}.call();
	}


	private boolean checkFormValidity() {
		if(username.getText().isEmpty()) return false;
		if(lastname.getText().isEmpty()) return false;
		if(firstname.getText().isEmpty()) return false;
		if(address.getText().isEmpty()) return false;
		if(age.getText().isEmpty()) return false;
		try{
			Integer.parseInt(age.getText());
		}catch (Exception e) {
			return false;
		}
		return true;
	}
}
